#ifndef __DAP_H__
#define __DAP_H__

#include <stddef.h>
#include <stdint.h>

// DAP Transfer Request
#define DAP_TRANSFER_APnDP              (1U<<0)
#define DAP_TRANSFER_RnW                (1U<<1)
#define DAP_TRANSFER_A2                 (1U<<2)
#define DAP_TRANSFER_A3                 (1U<<3)
#define DAP_TRANSFER_MATCH_VALUE        (1U<<4)
#define DAP_TRANSFER_MATCH_MASK         (1U<<5)
#define DAP_TRANSFER_TIMESTAMP          (1U<<7)

// DAP Transfer Response
#define DAP_TRANSFER_OK                 (1U<<0)
#define DAP_TRANSFER_WAIT               (1U<<1)
#define DAP_TRANSFER_FAULT              (1U<<2)
#define DAP_TRANSFER_ERROR              (1U<<3)
#define DAP_TRANSFER_MISMATCH           (1U<<4)

// Debug Port Register Addresses
#define DP_IDCODE                       0x00U   // IDCODE Register (SW Read only)
#define DP_ABORT                        0x00U   // Abort Register (SW Write only)
#define DP_CTRL_STAT                    0x04U   // Control & Status
#define DP_WCR                          0x04U   // Wire Control Register (SW Only)
#define DP_SELECT                       0x08U   // Select Register (JTAG R/W & SW W)
#define DP_RESEND                       0x08U   // Resend (SW Read Only)
#define DP_RDBUFF                       0x0CU   // Read Buffer (Read Only)

// SWD Sequence Info
#define SWD_SEQUENCE_CLK                0x3FU   // SWCLK count
#define SWD_SEQUENCE_DIN                0x80U   // SWDIO capture

// Configurable delay for clock generation
__attribute__((always_inline)) static __inline void PIN_DELAY_SLOW (uint32_t delay) {
  uint32_t count;

  count = delay;
  while (--count);
}

// Fixed delay for fast clock generation
#ifndef DELAY_FAST_CYCLES
#define DELAY_FAST_CYCLES       		0U      // Number of cycles: 0..3
#endif
__attribute__((always_inline)) static __inline void PIN_DELAY_FAST (void) {
#if (DELAY_FAST_CYCLES >= 1U)
  __nop();
#endif
#if (DELAY_FAST_CYCLES >= 2U)
  __nop();
#endif
#if (DELAY_FAST_CYCLES >= 3U)
  __nop();
#endif
}

// DAP Data structure
typedef struct {

  uint32_t    clock_delay;                      // Clock Delay
  uint32_t    timestamp;                        // Last captured Timestamp
  struct {                                      // Transfer Configuration
    uint8_t   idle_cycles;                      // Idle cycles after transfer
    uint8_t    padding[3];
  } transfer;
  struct {                                      // SWD Configuration
    uint8_t    turnaround;                      // Turnaround period
    uint8_t    data_phase;                      // Always generate Data Phase
  } swd_conf;
} DAP_Data_t;

//***********************************************************************
extern          DAP_Data_t DAP_Data_1;            // DAP Data

// Functions
extern void     SWD_Sequence_1    (uint32_t count, const uint8_t *data);
extern uint8_t  SWD_Transfer_1    (uint32_t request, uint32_t *data);
extern void     DAP_Setup_1 (void);

//***********************************************************************
extern          DAP_Data_t DAP_Data_2;            // DAP Data

// Functions
extern void     SWD_Sequence_2    (uint32_t count, const uint8_t *data);
extern uint8_t  SWD_Transfer_2    (uint32_t request, uint32_t *data);
extern void     DAP_Setup_2 (void);

//***********************************************************************
extern          DAP_Data_t DAP_Data_3;            // DAP Data

// Functions
extern void     SWD_Sequence_3    (uint32_t count, const uint8_t *data);
extern uint8_t  SWD_Transfer_3    (uint32_t request, uint32_t *data);
extern void     DAP_Setup_3 (void);


#endif  /* __DAP_H__ */
